#include <iostream>
#include <string>
#include <memory>

// 建造者模式:建造者模式是⼀种创建型设计模式， 使⽤多个简单的对象⼀步⼀步构建成⼀个复杂的对象，能够将⼀
// 个复杂的对象的构建与它的表⽰分离，提供⼀种创建对象的最佳⽅式。主要⽤于解决对象的构建过于
// 复杂的问题。
class Computer
{
public:
    Computer() {}
    void setBoard(const std::string &board) { _board = board; }
    void setDisplay(const std::string &display) { _display = display; }
    virtual void setOs() = 0;
    std::string toString()
    {
        std::string computer = "Comptuer:{\n";
        computer += "\tboard: " + _board + "\n";
        computer += "\tdisplay: " + _display + "\n";
        computer += "\tos: " + _os + "\n";
        computer += "}\n";
        return computer;
    }

protected:
    std::string _board;
    std::string _display;
    std::string _os;
};

//具体产品类

class MacBooK : public Computer
{
public:
    MacBooK() {}
    virtual void setOs()
    {
        _os = "Max Os X12";
    }
};

class Builder
{
public:
    virtual void buildBoard(const std::string &board) = 0;
    virtual void buildDisplay(const std::string &display) = 0;
    virtual void buildOs() = 0;
    virtual std::shared_ptr<Computer> build() = 0;
};

// 具体产品的具体建造者类
class MacBookBuilder : public Builder
{
public:
    MacBookBuilder() : _computer(new MacBooK()) {}
    virtual void buildBoard(const std::string &board)
    {
        _computer->setBoard(board);
    }

    virtual void buildDisplay(const std::string &display)
    {
        _computer->setDisplay(display);
    }

    virtual void buildOs()
    {
        _computer->setOs();
    }
    virtual std::shared_ptr<Computer> build()
    {
        return _computer;
    }

private:
    std::shared_ptr<Computer> _computer;
};
// 指挥者类，提供给调⽤者使⽤，通过指挥者来构造复杂产品

class Director
{
public:
    Director(Builder *builder) : _builder(builder) {}
    void construct(const std::string &board, const std::string &display)
    {
        _builder->buildBoard(board);
        _builder->buildDisplay(display);
        _builder->buildOs();
    }

private:
    std::shared_ptr<Builder> _builder;
};

int main()
{
    Builder *Builder = new MacBookBuilder();
    std::unique_ptr<Director> director(new Director(Builder));
    director->construct("英特尔主板", "VOC显示器");
    std::shared_ptr<Computer> computer = Builder->build();
    std::cout << computer->toString() << std::endl;
    return 0;
}